import ipaddress

from django.db import models
from django.utils.translation import gettext, gettext_lazy as _
from django.core.exceptions import ValidationError

from utils.model import UuidModel


class AAIUserInfo(UuidModel):
    class UserType(models.TextChoices):
        AAI = 'AAI', _('AAI')
        UMT = 'UMT', _('UMT')

    source_id = models.CharField(verbose_name=_('原始id'), max_length=36)
    true_name = models.CharField(verbose_name=_('姓名'), max_length=128)
    type = models.CharField(verbose_name=_('类型'), max_length=16, choices=UserType.choices, default=UserType.AAI.value)
    email = models.CharField(verbose_name=_('邮箱'), max_length=200, blank=True, default='')
    org_name = models.CharField(verbose_name=_('单位'), max_length=200, blank=True, default='')
    create_time = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    create_user = models.CharField(verbose_name=_('创建人'), max_length=255, blank=True, default='')
    update_time = models.DateTimeField(verbose_name=_('更新时间'), null=True, blank=True, default=None)
    update_user = models.CharField(verbose_name=_('更新人'), max_length=255, blank=True, default='')

    class Meta:
        db_table = 'aai_proxy_userinfo'
        ordering = ['-create_time']
        verbose_name = _('AAI用户信息')
        verbose_name_plural = verbose_name
        indexes = [
            models.Index(fields=['email'], name='idx_aai_proxy_user_email')
        ]


class SysProxyApp(UuidModel):
    name = models.CharField(verbose_name=_('应用名称'), max_length=254)
    url = models.CharField(
        verbose_name=_('应用地址'), max_length=254,
        help_text=_('应用的回调地址域名或IP，也支持域名通配符格式“*.example.com”，IP网段CIDR格式“192.168.1.0/24”'))
    state = models.BooleanField(verbose_name=_('可用'), default=True)
    create_time = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    create_user = models.CharField(verbose_name=_('创建人'), max_length=255, blank=True, default='')
    update_time = models.DateTimeField(verbose_name=_('更新时间'), null=True, blank=True, default=None)
    update_user = models.CharField(verbose_name=_('更新人'), max_length=255, blank=True, default='')

    class Meta:
        db_table = 'aai_proxy_sys_app'
        ordering = ['-create_time']
        verbose_name = _('应用回调地址白名单')
        verbose_name_plural = verbose_name

    def clean(self):
        if self.url:
            if '/' in self.url:
                try:
                    network = ipaddress.ip_network(self.url, strict=False)
                    self.url = str(network)
                except ValueError:
                    raise ValidationError({'url': gettext('无效的IP网段，支持CIDR 格式，例如192.168.1.0/24')})
            elif '*' in self.url:
                if not self.url.startswith("*."):
                    raise ValidationError({'url': gettext('无效的通配符格式域名，例如 “*.a.b”、“*.a.b.c”')})


class AAIProxyConfig(models.Model):
    class ConfigName(models.TextChoices):
        AAI_BASE_URL = 'aai_base_url', _('AAI base url')
        AAI_ISSUER = 'aai_issuer', _('AAI issuer')
        AAI_META_URL = 'aai_meta_url', _('AAI meta url')
        AAI_CLIENT_ID = 'aai_client_id', _('AAI客户端id')
        AAI_CLIENT_SECRET = 'aai_client_secret', _('AAI客户端密钥')
        AAI_LOGOUT_BACK_URL = 'aai_logout_back_url', _('AAI登出回调地址')
        PROXY_BASE_URL = 'proxy_base_url', _('AAI认证代理服务地址')
        JWT_PRIVATE_KEY = 'jwt_private_key', _('JWT签名加密私钥')
        JWT_PUBLIC_KEY = 'jwt_public_key', _('JWT签名加密公钥')

    # 配置的默认值，自动创建配置参数记录时填充的默认值
    value_defaults = {
        ConfigName.AAI_BASE_URL.value: 'https://aai.cstcloud.net/',
        ConfigName.AAI_ISSUER.value: 'https://aai.cstcloud.net/oidc/',
        ConfigName.AAI_META_URL.value: '/oidc/.well-known/openid-configuration',
        ConfigName.AAI_CLIENT_ID.value: '',
        ConfigName.AAI_CLIENT_SECRET.value: '',
        ConfigName.AAI_LOGOUT_BACK_URL.value: {
            'value': 'https://{hostname}/open/api/AAILogin/outRedirect', 'remark': '本AAI代理认证服务的登出回调地址'
        },
        ConfigName.PROXY_BASE_URL.value: {
            'value': 'https://{hostname}.cstcloud.net/', 'remark': '本AAI代理认证服务的地址'
        },
        ConfigName.JWT_PRIVATE_KEY.value: '',
        ConfigName.JWT_PUBLIC_KEY.value: '',
    }

    id = models.BigAutoField(primary_key=True)
    name = models.CharField(verbose_name=_('配置名称'), max_length=32, choices=ConfigName.choices)
    value = models.TextField(verbose_name=_('配置内容'), default='')
    remark = models.CharField(verbose_name=_('备注'), blank=True, max_length=255)
    creation_time = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    update_time = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    class Meta:
        db_table = 'aai_proxy_config'
        ordering = ['creation_time']
        verbose_name = _('AAI代理参数')
        verbose_name_plural = verbose_name
        constraints = [
            models.UniqueConstraint(fields=('name',), name='unique_aai_proxy_config_name')
        ]

    def __str__(self):
        return self.name
